/******************************************************************************************************************
* File:HumiditySensor.java
* Course: 17655
* Project: Assignment A3
* Copyright: Copyright (c) 2009 Carnegie Mellon University
* Versions:
*	1.0 March 2009 - Initial rewrite of original assignment 3 (ajl).
*
* Description:
*
* This class simulates a humidity sensor. It polls the event manager for events corresponding to changes in state
* of the humidifier or dehumidifier and reacts to them by trending the relative humidity up or down. The current
* relative humidity is posted to the event manager.
*
* Parameters: IP address of the event manager (on command line). If blank, it is assumed that the event manager is
* on the local machine.
*
* Internal Methods:
*	float GetRandomNumber()
*	boolean CoinToss()
*   void PostHumidity(EventManagerInterface ei, float humidity )
*
******************************************************************************************************************/
package Alarms;

import EventPackage.*;

public abstract class AbstractAlarm extends Participant
{
	protected int emergencyEvtId = 6;		
	protected int normalityEvtId = 12;	
	protected int armDisarmEvtId = 7;					
	protected int confirmationArmDisarmEvtId = -7;		
	protected int alarmLookingForControllerEvtId = 8;					
	protected int confirmationAlarmRegistrationEvtId = -8;		
	protected int monitorPingEvtId = 11;		
	protected int monitorPingReturnEvtId = -11;		
	protected String separator = "-@-";
	protected int previousStatus = Integer.MIN_VALUE;
	protected int status = -1;							// Current simulated status := -1: looking for controller; 0: disarmed; 1: armed/normal; 2: armed/Emergency
	protected String alarmId;							// Alarm's ID
	protected int lookingForControllerTimeOut = 100;		
	protected int Height = 150;
	
	public AbstractAlarm(String title, int Xpos, int Ypos, int mwWidth, int subSystemHaltEnvId, String sensor_name) {
		super();
		
		setParameters(title, Xpos, Ypos, Height, mwWidth, subSystemHaltEnvId, sensor_name);
		
	}

	protected void initialPostPhase(){
		switch (status) {
		case -1: 
			postEvent(alarmLookingForControllerEvtId, alarmId + separator + name);
			mw.WriteMessage("Alarm: [" + alarmId + "] Status: looking for controller");
			break;
		case 0: 
			if (status != previousStatus) {
				previousStatus = status;
				mw.WriteMessage("Alarm: [" + alarmId + "] Status: disarmed");
			}
			break;
		case 1:
			if (status != previousStatus) {
				previousStatus = status;
				mw.WriteMessage("Alarm: [" + alarmId + "] Status: armed / normal");
			}
			break;
		case 2:
			if (status != previousStatus) {
				previousStatus = status;
				mw.WriteMessage("Alarm: [" + alarmId + "] Status: !!! EMERGENCY !!!");
			}
			break;
		default:
			mw.WriteMessage("Alarm: [" + alarmId + "] ERROR: Unrecognized status = " + status);
		}
	}
	
	protected void handlePhase(){
		if (Evt.GetEventId() == subSystemHaltEnvId) {
			halt();
		}
		
		if ((status == -1) && ( Evt.GetEventId() == confirmationAlarmRegistrationEvtId) && (Evt.GetMessage().equals(alarmId + separator + name))) {
			status = 0;
			mw.WriteMessage("Alarm: [" + alarmId + "] Found a controller");
		} // if
		
		if (status == -1) {
			lookingForControllerTimeOut --;
			
			if (lookingForControllerTimeOut < 0) {
		
				mw.WriteMessage("  FAILURE:: no controller found" );
				halt();
			}
		}
		
		if (Evt.GetEventId() == monitorPingEvtId) {
			postEvent(monitorPingReturnEvtId, alarmId + separator + name + separator + status);
		}

		if (Evt.GetEventId() == armDisarmEvtId) {
			String evtMsg = Evt.GetMessage();
			String evtAlarmId = evtMsg.substring(0, evtMsg.length() - 1);
			char evtCommand = evtMsg.charAt(evtMsg.length() - 1);
			
			if (evtAlarmId.equals(alarmId)) { 
				if (evtCommand == '1')  {
					if (status != 1) status = 1;
					postEvent(confirmationArmDisarmEvtId, evtMsg);
				}
			}

			if (evtAlarmId.equals(alarmId)) { 
				if (evtCommand == '0')  {
					if (status != 0) status = 0;
					postEvent(confirmationArmDisarmEvtId, evtMsg);
				}
			}
		}
		
		customEventHandler();
	}
	
	protected abstract void customEventHandler();
	
	protected abstract void dispose();
	
	
	protected void postEmergency()
	{
		postEvent(emergencyEvtId, alarmId);
	} // postEmergency

	protected void postNormality()
	{
		postEvent(normalityEvtId, alarmId);
	} // postEmergency

	public boolean isArmed() {
		return ((status == 1) || (status == 2)); 
	}
	
	@Override
	protected void finalPostPhase() {
		// TODO Auto-generated method stub
		
	}
} // AbstractAlarm